package com.usbserial.scale.adapter.mettler;

import com.usbserial.core.SerialConfig;
import com.usbserial.core.SerialPort;
import com.usbserial.core.UsbSerialDeviceInfo;
import com.usbserial.exception.ParseException;
import com.usbserial.exception.UsbSerialException;
import com.usbserial.scale.ScaleData;
import com.usbserial.scale.adapter.ScaleAdapter;
import com.usbserial.scale.adapter.ScaleCommand;
import com.usbserial.scale.adapter.ScaleDeviceIdentifier;

import java.nio.charset.StandardCharsets;

/**
 * Mettler Toledo ACS-SY (VIVA) 电子秤适配器
 *
 * 设备信息：
 * - 制造商：Mettler Toledo
 * - 型号：ACS-SY (VIVA) 4111
 * - USB芯片：CH340 (VID=0x1A86 PID=0x7523)
 * - 协议：MT-SICS (Mettler Toledo Standard Interface Command Set)
 *
 * 通信模式：
 * - 请求-响应模式（需要发送命令才能获取数据）
 * - 与Aclas被动推送模式不同
 *
 * MT-SICS 常用命令：
 * - S\r\n   : 发送稳定重量
 * - SI\r\n  : 立即发送重量
 * - SR\r\n  : 连续发送重量
 * - Z\r\n   : 清零
 * - T\r\n   : 去皮
 * - I0\r\n  : 查询设备信息
 *
 * 响应格式：
 * - 格式：<Status> <Command> <Value> <Unit>\r\n
 * - 示例：S S     12.345 kg\r\n
 * - 状态码：S=稳定, D=动态, I=立即, +=超上限, -=低于下限, E=错误
 */
public class MettlerToledoAdapter implements ScaleAdapter {

    private static final String NAME = "Mettler Toledo MT-SICS Adapter";
    private static final String VERSION = "1.0.0";

    // MT-SICS 命令
    private static final String CMD_SEND_STABLE = "S\r\n";       // 发送稳定重量
    private static final String CMD_SEND_IMMEDIATE = "SI\r\n";   // 立即发送重量
    private static final String CMD_SEND_REPEAT = "SR\r\n";      // 连续发送重量
    private static final String CMD_ZERO = "Z\r\n";              // 清零
    private static final String CMD_TARE = "T\r\n";              // 去皮
    private static final String CMD_TARE_CLEAR = "TAC\r\n";      // 清除去皮
    private static final String CMD_RESET = "@\r\n";             // 复位
    private static final String CMD_INFO = "I0\r\n";             // 设备信息

    private SerialPort port;
    private UsbSerialDeviceInfo deviceInfo;

    @Override
    public String getName() {
        return NAME;
    }

    @Override
    public ScaleDeviceIdentifier getDeviceIdentifier() {
        // 注意：Mettler Toledo 与 Aclas 使用相同的 VID/PID
        // 需要在使用时手动选择适配器类型
        return new ScaleDeviceIdentifier.Builder()
            .manufacturer("Mettler.*Toledo")  // 支持正则匹配
            .model("ACS.*")                    // 支持 ACS-SY 等型号
            .vendorId(0x1A86)                  // CH340 芯片
            .productId(0x7523)
            .build();
    }

    @Override
    public void initialize(SerialPort port, UsbSerialDeviceInfo deviceInfo) throws UsbSerialException {
        this.port = port;
        this.deviceInfo = deviceInfo;

        // MT-SICS 设备初始化
        // 发送复位命令
        try {
            sendRawCommand(CMD_RESET);
            Thread.sleep(500);  // 等待设备复位

            // 查询设备信息（可选）
            sendRawCommand(CMD_INFO);
            Thread.sleep(200);

            // 启动连续发送模式
            sendRawCommand(CMD_SEND_REPEAT);
        } catch (InterruptedException e) {
            throw new UsbSerialException("初始化被中断", e);
        }
    }

    @Override
    public ScaleData parseData(byte[] rawData) throws ParseException {
        if (rawData == null || rawData.length == 0) {
            throw new ParseException("数据为空");
        }

        // 转换为ASCII字符串
        String response = new String(rawData, StandardCharsets.US_ASCII).trim();

        // MT-SICS 响应格式：<Status> <Command> <Value> <Unit>
        // 示例：S S     12.345 kg
        //       S D      0.123 g
        //       S I    150.000 g

        // 分割响应（使用空格分割）
        String[] parts = response.split("\\s+");

        if (parts.length < 4) {
            throw new ParseException("MT-SICS响应格式无效: " + response);
        }

        // 解析状态字符
        char responseStatus = parts[0].charAt(0);
        char commandEcho = parts[1].charAt(0);

        // 解析重量值
        String weightStr = parts[2];
        double weight = parseWeight(weightStr);

        // 解析单位
        String unitStr = parts[3];
        ScaleData.WeightUnit unit = parseUnit(unitStr);

        // 解析状态
        ScaleData.ScaleStatus status = parseStatus(responseStatus);

        return new ScaleData(weight, unit, status);
    }

    /**
     * 解析 MT-SICS 状态字符
     */
    private ScaleData.ScaleStatus parseStatus(char statusChar) {
        switch (statusChar) {
            case 'S':  // Stable - 稳定
                return ScaleData.ScaleStatus.STABLE;
            case 'D':  // Dynamic - 动态（不稳定）
                return ScaleData.ScaleStatus.UNSTABLE;
            case 'I':  // Immediate - 立即（响应SI命令）
                return ScaleData.ScaleStatus.UNSTABLE;
            case '+':  // 超上限
                return ScaleData.ScaleStatus.OVERLOAD;
            case '-':  // 低于下限
                return ScaleData.ScaleStatus.UNDERLOAD;
            case '>':  // 超量程
                return ScaleData.ScaleStatus.OVERLOAD;
            case '<':  // 低于量程
                return ScaleData.ScaleStatus.UNDERLOAD;
            case 'E':  // Error - 错误
                return ScaleData.ScaleStatus.ERROR;
            default:
                return ScaleData.ScaleStatus.UNSTABLE;
        }
    }

    /**
     * 解析重量值
     */
    private double parseWeight(String weightStr) throws ParseException {
        try {
            return Double.parseDouble(weightStr);
        } catch (NumberFormatException e) {
            throw new ParseException("无效的重量值: " + weightStr, e);
        }
    }

    /**
     * 解析单位
     */
    private ScaleData.WeightUnit parseUnit(String unitStr) {
        String normalized = unitStr.trim().toLowerCase();
        switch (normalized) {
            case "g":
            case "gram":
                return ScaleData.WeightUnit.GRAM;
            case "kg":
            case "kilogram":
                return ScaleData.WeightUnit.KILOGRAM;
            case "lb":
            case "lbs":
            case "pound":
                return ScaleData.WeightUnit.POUND;
            case "oz":
            case "ounce":
                return ScaleData.WeightUnit.OUNCE;
            default:
                // 默认返回克
                return ScaleData.WeightUnit.GRAM;
        }
    }

    @Override
    public void sendCommand(ScaleCommand command, Object... params) throws UsbSerialException {
        String mtCommand;
        switch (command) {
            case ZERO:
                mtCommand = CMD_ZERO;
                break;
            case TARE:
                mtCommand = CMD_TARE;
                break;
            case READ_WEIGHT:
                mtCommand = CMD_SEND_STABLE;
                break;
            case GET_STATUS:
                mtCommand = CMD_INFO;
                break;
            case RESET:
                mtCommand = CMD_RESET;
                break;
            default:
                throw new UnsupportedOperationException(
                    "MT-SICS不支持命令: " + command);
        }

        sendRawCommand(mtCommand);
    }

    /**
     * 发送原始MT-SICS命令
     */
    private void sendRawCommand(String command) throws UsbSerialException {
        if (port == null) {
            throw new UsbSerialException("串口未初始化");
        }

        try {
            byte[] cmdBytes = command.getBytes(StandardCharsets.US_ASCII);
            port.write(cmdBytes);
        } catch (Exception e) {
            throw new UsbSerialException("发送MT-SICS命令失败: " + command.trim(), e);
        }
    }

    @Override
    public SerialConfig getRecommendedConfig() {
        // Mettler Toledo 常用配置
        // 旧款设备可能使用 4800，新款通常使用 9600
        return SerialConfig.builder()
            .baudRate(9600)  // 可能需要尝试 4800
            .dataBits(SerialConfig.DATABITS_8)
            .stopBits(SerialConfig.STOPBITS_1)
            .parity(SerialConfig.PARITY_NONE)
            .flowControl(SerialConfig.FLOW_CONTROL_OFF)
            .build();
    }

    @Override
    public void release() {
        // 停止连续发送模式（如果支持）
        // 注意：某些设备可能没有停止命令，只能通过断开连接
        this.port = null;
        this.deviceInfo = null;
    }

    @Override
    public String getVersion() {
        return VERSION;
    }
}
